import importlib._bootstrap_external as bse
from importlib._bootstrap_external import _get_supported_file_loaders as builtin_file_loaders
from importlib import reload
__all__=['register_override']
import sys
hooks_table={}
class SourceFileLoader(bse.SourceFileLoader):
    def exec_module(self,module):
        #~ print(dir(module))
        #~ if hasattr(module,'__all__') is False:
            #~ attrs=list(filter(lambda a : a.startswith('__') is False,dir(module)))
            #~ module.__old_attrs__=attrs
            #~ module.__all__=attrs
        exec_stat=super(SourceFileLoader,self).exec_module(module)
        patched_objects={}
        for i in sorted(hooks_table.keys(),key=lambda s:len(s),reverse=True):
            if module.__file__.startswith(i):
                patched_objects.update(hooks_table[i](module))
        print(self,module,type(self))
        super(SourceFileLoader,self)

        #~ if hasattr(module,'__all__') is False:
        attrs=list(filter(lambda a : a.startswith('__') is False,dir(module)))
        module.__jy_patched__=[]

        _all=[]
        for i in attrs:
            obj=getattr(module,i)
            if i in patched_objects and obj is patched_objects[i]:
                #~ print(i,obj)
                module.__jy_patched__.append((i,obj))
            else:
                _all.append(i)
        if hasattr(module,'__all__') is False:
            module.__all__=_all
        #~ print(module,module.__all__)
        return exec_stat
loader_details=[]
for loader,suffixes in builtin_file_loaders():
    if loader is bse.SourceFileLoader:
        loader=SourceFileLoader
    loader_details.append((loader,suffixes))
class FileFinder(bse.FileFinder):
    def __init__(self, path):
        super(FileFinder,self).__init__(path,*loader_details)


def init_override():
    def path_hook(path):
        for i in hooks_table:
            if path.startswith(i):
                #~ print('hook',path)
                return FileFinder(path)
        raise ImportError()
    import sys
    if path_hook != sys.path_hooks[0]:
        if path_hook in sys.path_hooks:sys.path_hooks.remove(path_hook)
        sys.path_hooks.insert(0,path_hook)

import os.path as op
def register_override(path,hook=lambda module:module):
    init_override()
    path=op.abspath(path)
    if path in sys.path_importer_cache:
        sys.path_importer_cache[path]=FileFinder(path)
        print('register',path)
    else:
        #~ print('register FAIL',path,sys.path_importer_cache[path])
        sys.path_importer_cache[path]=FileFinder(path)

    hooks_table[path]=hook
    for s in sys.modules:
        if s == '__main__': # main module can not be reloaded
            continue
        m=sys.modules[s]
        if hasattr(m,'__file__') and op.abspath(m.__file__).startswith(path):
            #~ if __debug__ : print('reload1',m,file=sys.stderr)
            reload(m)
